use crate::errors::map_rmpv_write_err;
use crate::Result;
use alloc::string::String;
use alloc::vec::Vec;
use embed_std::warnln;
use rmpv::encode::write_value;
use rmpv::{Utf8String, Value};

pub enum RequestMethod {
    Get,
    Put,
    Post,
    Delete,
}

pub struct CallRequestBuilder<'a> {
    pub url: String,
    pub method: RequestMethod,
    pub headers: Vec<(String, String)>,
    pub body: Option<&'a [u8]>,
}

impl<'a> CallRequestBuilder<'a> {
    pub fn new() -> Self {
        Self {
            url: String::from(""),
            method: RequestMethod::Get,
            headers: Vec::new(),
            body: None,
        }
    }
    pub fn build(self, buff: &mut Vec<u8>) -> Result<()> {
        let mut root: Vec<(Value, Value)> = Vec::new();
        root.push((
            Value::String(Utf8String::from("u")),
            Value::String(Utf8String::from(self.url)),
        ));
        if !self.headers.is_empty() {
            warnln!("@TODO: header not support");
        } else {
            root.push((Value::String(Utf8String::from("h")), Value::Map(Vec::new())));
        }
        root.push((
            Value::String(Utf8String::from("m")),
            Value::String(Utf8String::from(match self.method {
                RequestMethod::Get => "GET",
                RequestMethod::Put => "PUT",
                RequestMethod::Post => "POST",
                RequestMethod::Delete => "DELETE",
            })),
        ));
        if let Some(payload) = self.body {
            root.push((Value::String(Utf8String::from("b")), Value::from(payload)));
        } else {
            root.push((Value::String(Utf8String::from("b")), Value::Map(Vec::new())));
        }
        write_value(buff, &Value::Map(root)).map_err(map_rmpv_write_err)?;
        Ok(())
    }
}
